package com.magnificent.atlantis.client.ui.creator.dialogs;

import com.magnificent.atlantis.client.data.task.creator.AbstractCreatorTask;
import com.magnificent.atlantis.client.data.task.creator.CreatorBasicTask;
import com.magnificent.atlantis.client.data.task.creator.CreatorMeetingTask;
import com.magnificent.atlantis.client.ui.common.DependencyTableModel;
import com.magnificent.atlantis.client.ui.common.TaskDialog;
import com.magnificent.atlantis.client.ui.creator.CreatorUI;
import com.magnificent.commons.utils.TimeConstants;
import com.magnificent.commons.utils.collections.CollectionsUtils;

import javax.swing.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * User: Babanin
 * Date: 07.02.2009
 * Time: 2:08:15
 */
public class CreatorTaskDialog extends TaskDialog {

    private AbstractCreatorTask dependencySelectedTask;
    private List<AbstractCreatorTask> dependencyTaskList;
    private CreatorDependencyTableModel dependencyTableModel;

    private boolean edit;
    private AbstractCreatorTask task;
    private List<AbstractCreatorTask> taskList;

    public CreatorTaskDialog(TaskType taskType, List<AbstractCreatorTask> taskList, DialogConnector<Object> dialogConnector, AbstractCreatorTask task) {
        super(CreatorUI.getFrame(), taskType, task != null, dialogConnector, new CreatorDependencyTableModel(new ArrayList<AbstractCreatorTask>()));

        edit = task != null;
        this.taskList = taskList;
        dependencyTaskList = new ArrayList<AbstractCreatorTask>();
        dependencyTableModel = (CreatorDependencyTableModel) dependencyTaskTable.getModel();
        this.task = edit ? task : (taskType == TaskType.MEETING ? new CreatorMeetingTask() : new CreatorBasicTask());

        initLocalControls();
    }

    private void initLocalControls() {
        if (edit) {
            nameTextField.setText(task.getName());
            descriptionTextArea.setText(task.getDescription());

            taskCombobox.setModel(new DefaultComboBoxModel(addEmptyElement(onlyPreviousTasks(taskList, task.getId()).toArray())));
            taskCombobox.setSelectedIndex(task.getDependencyTaskId());
            updateDependencyTextFields(task.getDependencyTaskId());

            long taskTime = task.getDependencyTaskTime();
            if (taskTime != 0) {
                dayTextField.setText("" + (taskTime / TimeConstants.MLS_IN_DAY));
                hoursTextField.setText("" + ((taskTime % TimeConstants.MLS_IN_DAY) / TimeConstants.MLS_IN_HOUR));
            }

            dependencyTaskList = tasksById(task.getDependencyTasks(), taskList);
            dependencyTableModel.setTasks(dependencyTaskList);
        } else {
            taskCombobox.setModel(new DefaultComboBoxModel(addEmptyElement(taskList.toArray())));
            updateDependencyTextFields(0);
        }
    }

    protected void dependencyTableSelectionChanged(int selectedRow) {
        if (selectedRow >= 0) {
            dependencySelectedTask = dependencyTaskList.get(selectedRow);
            deleteDependencyButton.setEnabled(true);
        } else {
            dependencySelectedTask = null;
            deleteDependencyButton.setEnabled(false);
        }
    }

    protected void addDependencyButtonPressed() {
        final Collection<? extends Object> creatorTasks = CollectionsUtils.exclude(onlyPrevious(CreatorTaskDialog.this.task), dependencyTaskList);
        new TaskSelectorDialog(CreatorTaskDialog.this, creatorTasks, new DialogConnector<Object>() {
            public boolean objectSelected(Object obj) {
                dependencyTaskList.add((AbstractCreatorTask) obj);
                dependencyTableModel.setTasks(dependencyTaskList);

                return true;
            }
        }).setVisible(true);
    }

    protected void deleteDependencyButtonPressed() {
        dependencyTaskList.remove(dependencySelectedTask);
        dependencyTableModel.setTasks(dependencyTaskList);
        deleteDependencyButton.setEnabled(false);
    }

    protected Object getTask() {
        return task;
    }

    protected boolean checkFields() {
        String name = nameTextField.getText().trim();
        String description = descriptionTextArea.getText().trim();

        if (name.equals("") || description.equals("")) {
            return false;
        }

        if (!edit) {
            task.setId(taskList.size() + 1);
        }

        task.setName(name);
        task.setDescription(description);

        task.setDependencyTasks(getListOfTaskIds(dependencyTableModel));

        if (taskCombobox.getSelectedIndex() > 0) {
            int dependencyTaskId = ((AbstractCreatorTask) taskCombobox.getSelectedItem()).getId();
            try {
                int days = Integer.parseInt(dayTextField.getText().trim());
                int hours = Integer.parseInt(hoursTextField.getText().trim());

                task.setDependencyTaskId(dependencyTaskId);
                task.setDependencyTaskTime(TimeConstants.MLS_IN_DAY * days + TimeConstants.MLS_IN_HOUR * hours);

                return true;
            } catch (NumberFormatException nfe) {
                return false;
            }
        } else {
            task.setDependencyTaskId(-1);
            task.setDependencyTaskTime(0);
        }

        return true;
    }

    private List<AbstractCreatorTask> tasksById(List<Integer> dependencyTasks, List<AbstractCreatorTask> taskList) {
        List<AbstractCreatorTask> result = new ArrayList<AbstractCreatorTask>(dependencyTasks.size());

        for (Integer id : dependencyTasks) {
            for (AbstractCreatorTask abstractTask : taskList) {
                if (abstractTask.getId() == id) {
                    result.add(abstractTask);
                    break;
                }
            }
        }

        return result;
    }

    private List<AbstractCreatorTask> onlyPreviousTasks(List<AbstractCreatorTask> taskList, int id) {
        List<AbstractCreatorTask> result = new ArrayList<AbstractCreatorTask>();

        for (AbstractCreatorTask task : taskList) {
            if (task.getId() < id) {
                result.add(task);
            }
        }

        return result;
    }

    private List<AbstractCreatorTask> onlyPrevious(AbstractCreatorTask task) {
        if (edit) {
            int taskPos = taskList.indexOf(task);

            if (taskPos >= 0) {
                return taskList.subList(0, taskPos);
            }
        }

        return taskList;
    }

    private List<Integer> getListOfTaskIds(DependencyTableModel taskTableModel) {
        List<Integer> result = new ArrayList<Integer>();
        List<AbstractCreatorTask> tasks = taskTableModel.getTasks();

        for (AbstractCreatorTask abstractTask : tasks) {
            result.add(abstractTask.getId());
        }

        return result;
    }

    public static void createBasicTask(List<AbstractCreatorTask> taskList, DialogConnector<Object> dialogConnector) {
        new CreatorTaskDialog(TaskType.SIMPLE, taskList, dialogConnector, null).setVisible(true);
    }

    public static void createMeetingTask(List<AbstractCreatorTask> taskList, DialogConnector<Object> dialogConnector) {
        new CreatorTaskDialog(TaskType.MEETING, taskList, dialogConnector, null).setVisible(true);
    }

    public static void editBasicTask(CreatorBasicTask task, List<AbstractCreatorTask> taskList, DialogConnector<Object> dialogConnector) {
        new CreatorTaskDialog(TaskType.SIMPLE, taskList, dialogConnector, task).setVisible(true);
    }

    public static void editMeetingTask(CreatorMeetingTask task, List<AbstractCreatorTask> taskList, DialogConnector<Object> dialogConnector) {
        new CreatorTaskDialog(TaskType.MEETING, taskList, dialogConnector, task).setVisible(true);
    }

    public static class CreatorDependencyTableModel extends DependencyTableModel<AbstractCreatorTask> {
        private CreatorDependencyTableModel(List<AbstractCreatorTask> tasks) {
            super(tasks);
        }

        public Object getValueAt(int row, int column) {
            AbstractCreatorTask task = tasks.get(row);

            if (column == 0) {
                return task.getId();
            }

            return task.getName();
        }
    }
}
